package me.zhengjie.modules.website.controller;

import com.jdone.enc.EncInterface;
import me.zhengjie.modules.website.domain.VisitReservationTable;
import me.zhengjie.modules.website.service.VisitReservationTableService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import me.zhengjie.modules.website.domain.ReservationDetailTable;
import me.zhengjie.modules.website.service.ReservationDetailTableService;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.GetMapping;
import me.zhengjie.modules.website.domain.PageResult;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

/**
 * @author system
 * @since 2024-10-23 22:22:57
 */
@RestController
@RequestMapping("/api/reservationDetailTable")
@Api(tags = " 网页-预约参观申请管理")
public class ReservationDetailTableController {

    @Autowired
    private ReservationDetailTableService reservationDetailTableService;

    @Autowired
    private VisitReservationTableService visitReservationTableService;

    /**
     * 分页查询
     *
     * @param params    查询参数
     * @param startDate 起始时间
     * @param endDate   结束时间
     * @return 分页结果
     */
    @ApiOperation(value = "分页查询", notes = "分页查询", produces = "application/json")
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功")})
    @PostMapping("/findPage")
    public ResponseEntity<PageResult<ReservationDetailTable>> findPage(
            @RequestBody ReservationDetailTable params,
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startDate,
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endDate,
            Pageable pageable) {

        // 调用服务层方法执行分页查询
        PageResult<ReservationDetailTable> result = reservationDetailTableService.findPage(params, startDate, endDate, pageable);
        verifyAndDecrypt(result.getContent());
        return ResponseEntity.ok(result);
    }


    /**
     * 根据预约访客表ID查询所有预约详情，并按预约时间排序（分页）
     *
     * @param reservationId 预约访客表ID
     * @param pageable      分页参数
     * @return ApiResponse 分页查询的预约详情数据
     */
    @ApiOperation(value = "根据预约访客表ID查询所有预约详情", notes = "根据预约访客表ID查询所有预约详情", produces = "application/json")
    @GetMapping("/findByReservationId/{reservationId}")
    public ResponseEntity<Page<ReservationDetailTable>> getReservationDetailsByReservationId(
            @PathVariable("reservationId") Integer reservationId, Pageable pageable) {

        // 查询预约详情并按预约时间排序（分页）
        Page<ReservationDetailTable> result = reservationDetailTableService
                .findReservationDetailsByReservationId(reservationId, pageable);
        verifyAndDecrypt(result.getContent());
        return ResponseEntity.ok(result);
    }

    /**
     * 列表查询
     *
     * @param params
     * @return
     */
    @ApiOperation(value = "列表查询", notes = "列表查询", produces = "application/json")
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功")})
    @PostMapping("/findList")
    public ResponseEntity<List<ReservationDetailTable>> findList(@RequestBody ReservationDetailTable params) {

        List<ReservationDetailTable> result = reservationDetailTableService.findList(params);
        verifyAndDecrypt(result);
        return ResponseEntity.ok(result);
    }

    /**
     * 查询
     *
     * @param id
     * @return
     */
    @ApiOperation(value = "查询", notes = "查询详情")
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功")})
    @GetMapping("findById/{id}")
    public ResponseEntity<ReservationDetailTable> findById(@PathVariable("id") Long id) {
        ReservationDetailTable reservationDetailTable = reservationDetailTableService.findById(id);
        verifyAndDecrypt(reservationDetailTable);
        return ResponseEntity.ok(reservationDetailTable);
    }

    /**
     * 新增
     *
     * @param reservationDetailTable
     * @return
     */
    @ApiOperation(value = "新增", notes = "新增")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PostMapping("/insert")
    public ResponseEntity<ReservationDetailTable> insertByEndBack(@Validated @RequestBody ReservationDetailTable reservationDetailTable) {
        reservationDetailTable = encryptAndSign(reservationDetailTable);
        ReservationDetailTable result = reservationDetailTableService.insert(reservationDetailTable);
        return ResponseEntity.ok(result);
    }

    /**
     * 展示平台-预约新增
     *
     * @param reservationDetailTable
     * @return
     */
    @ApiOperation(value = "展示平台-预约新增", notes = "展示平台-预约新增")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PostMapping("/website/insert")
    public ResponseEntity<?> insert(@Validated @RequestBody ReservationDetailTable reservationDetailTable) {
        // 获取预约时间
        Date reservationTime = reservationDetailTable.getReservationTime();

        // 调用服务方法处理预约
        VisitReservationTable updatedReservation = visitReservationTableService.handleReservation(reservationDetailTable.getReservationId(), reservationDetailTable.getPeopleNum());

        // 判断返回值
        if (updatedReservation != null) {// 如果更新成功，继续保存预约详细信息
            reservationDetailTable = encryptAndSign(reservationDetailTable);
            ReservationDetailTable result = reservationDetailTableService.insert(reservationDetailTable);
            return ResponseEntity.ok(result);
        } else {// 如果更新失败，返回预约失败提示
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("预约失败：没有剩余名额");
        }
    }

    /**
     * 修改
     *
     * @param reservationDetailTable
     * @return
     */
    @ApiOperation(value = "修改", notes = "修改数据")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PutMapping("/update")
    public ResponseEntity<ReservationDetailTable> update(@Validated @RequestBody ReservationDetailTable reservationDetailTable) {
        ReservationDetailTable encryptAndSign = encryptAndSign(reservationDetailTable);
        ReservationDetailTable result = reservationDetailTableService.update(encryptAndSign);
        return ResponseEntity.ok(result);
    }

    /**
     * 删除
     *
     * @param id
     * @return
     */
    @ApiOperation(value = "删除", notes = "删除数据")
    @DeleteMapping("delete/{id}")
    public ResponseEntity<Void> delete(@PathVariable("id") Long id) {
        reservationDetailTableService.delete(id);
        return ResponseEntity.ok(null);
    }


    /**
     * 审批预约详情接口
     *
     * @param id          预约详情的 ID
     * @param reviewNotes 审批意见
     * @return ResponseEntity<ApiResponse < String>> 审批结果
     */
    @ApiOperation(value = "审批预约详情", notes = "根据预约详情 ID 更新审批字段并将状态设置为通过")
    @PutMapping("/approve/{id}")
    public ResponseEntity<Object> approveReservationDetail(
            @PathVariable Long id,
            @RequestParam(value = "reviewNotes", required = true) Boolean reviewNotes,
            @RequestParam(value = "responseContent", required = false) String responseContent) {
        reservationDetailTableService.approveReservationDetail(id, reviewNotes, responseContent);
        return ResponseEntity.ok("审批成功");
    }


    /**
     * 对 ReservationDetailTable 里的敏感字段加密，并生成完整性 SM3 签名。
     *
     * @param detail 原始数据对象
     * @return 同一个对象，reserverName/contactPhone 被加密，sm3 被更新
     */
    public static ReservationDetailTable encryptAndSign(ReservationDetailTable detail) {
        if (detail == null) {
            return null;
        }

        // 1. SM4 加密敏感内容
        String encryptedName = EncInterface.encrypt(detail.getReserverName());
        String encryptedPhone = EncInterface.encrypt(detail.getContactPhone());
        detail.setReserverName(encryptedName);
        detail.setContactPhone(encryptedPhone);

        // 2. 拼装待签字符串（使用已加密的字段）
        String toSign = encryptedName
                + "|" + encryptedPhone
                + "|" + detail.getPeopleNum()
                + "|" + detail.getCreateTime();

        // 3. 生成 SM3 完整性签名（或 HMAC-SM3）
        String signature = EncInterface.generateHmac(toSign);
        detail.setSm3(signature);

        return detail;
    }

    /**
     * 对单条记录：先验签，再根据结果决定是否解密敏感字段，
     * 并把 sm3 字段替换成 "true"/"false"。
     */
    public static void verifyAndDecrypt(ReservationDetailTable record) {
        if (record == null) return;

        // 1. 拼签名串（使用加密后的字段）
        String toSign = record.getReserverName()
                + "|" + record.getContactPhone()
                + "|" + record.getPeopleNum()
                + "|" + record.getCreateTime();

        // 2. 验签
        boolean valid = EncInterface.verifyHmac(toSign, record.getSm3());

        // 3. 覆盖 sm3 为校验结果
        record.setSm3(Boolean.toString(valid));

        // 4. 若通过，解密敏感字段
        if (valid) {
            record.setReserverName(EncInterface.decrypt(record.getReserverName()));
            record.setContactPhone(EncInterface.decrypt(record.getContactPhone()));
        }
    }

    /**
     * 对多条记录批量处理，内部调用单条方法。
     */
    public static void verifyAndDecrypt(List<ReservationDetailTable> records) {
        if (records == null) return;
        for (ReservationDetailTable r : records) {
            verifyAndDecrypt(r);
        }
    }
}